package jannex.mapping;

import jannex.Builder;
import jannex.sql.JxResultSet;
import jannex.sql.JxResultSetMetaData;

import java.util.Set;

public class DefaultResultSetHandler<E> implements ResultSetHandler<E> {

    private final MappedField<E>[] fields;
    private final ResultSetHandler<Object>[] subHandlers;

    private final Builder<E> objectBuilder;
    private final Set<String> duplicatedLabels;

    public DefaultResultSetHandler(MappedField<E>[] fields, ResultSetHandler<Object>[] subHandlers,
                                   Builder<E> objectBuilder, Set<String> duplicatedLabels) {
        this.fields = fields;
        this.subHandlers = subHandlers;
        this.objectBuilder = objectBuilder;
        this.duplicatedLabels = duplicatedLabels;
    }

    @Override
    public E handle(JxResultSet resultSet) {
        E e = objectBuilder.build();
        int subHandlerIndex = 0;
        for (MappedField<E> mappedField : fields) {
            if (!mappedField.hasFields()) {
                mappedField.getSetter().set(e, getObject(mappedField, resultSet));
            } else {
                ResultSetHandler<?> subHandler = subHandlers[subHandlerIndex++];
                Object innerObject = subHandler.handle(resultSet.subSetFromTable(mappedField.getTable()));
                mappedField.getSetter().set(e, innerObject);
            }

        }
        return e;
    }

    private Object getObject(MappedField<E> field, JxResultSet resultSet) {
        Object object = null;
        if (duplicatedLabels != null && duplicatedLabels.contains(field.getLabel())) {
            JxResultSetMetaData metaData = resultSet.getMetaData();
            for (int col = 1; col <= metaData.getColumnCount(); col++) {
                if (field.getLabel().equalsIgnoreCase(metaData.getColumnLabel(col))) {
                    if (field.getTable().equalsIgnoreCase(metaData.getTableName(col))) {
                        object = resultSet.getObject(col, field.getType());
                        break;
                    }
                }
            }
        }
        if (object == null) {
            object = resultSet.getObject(field.getLabel(), field.getType());
        }
        return object;
    }

}
